package spindles.gwt.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.antlr.stringtemplate.StringTemplate;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import spindles.api.db.DAO;
import spindles.api.db.DBGateway;
import spindles.api.domain.Epoch;
import spindles.api.domain.SamplingRate;
import spindles.api.services.ExportService;
import spindles.api.util.ApplicationException;
import spindles.api.util.UserException;

import com.mathworks.toolbox.javabuilder.MWException;
import com.mathworks.toolbox.javabuilder.web.MWHttpSessionBinder;
import com.mathworks.toolbox.javabuilder.webfigures.WebFigure;

public class PlotServlet extends HttpServlet {
	transient final Logger log = LoggerFactory.getLogger(PlotServlet.class);

	/**
	 * 
	 */
	private static final long serialVersionUID = 8153548892576569127L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		disposeWebFigure(request);
		
		PrintWriter out = null;

		try {
			
			out = response.getWriter();
			
			String plotType = request.getParameter("plotType");
			
			String epochID = request.getParameter("epochID");
			String partID = request.getParameter("partID");
			String fromTime = request.getParameter("from");
			String toTime = request.getParameter("to");
			
			boolean softCriterion = Boolean.parseBoolean(request.getParameter("soft"));
			boolean raw = Boolean.parseBoolean(request.getParameter("raw"));			
			
			WebFigure wf = null;
			if (plotType.equals("epoch")) {
				wf = getEpochPlot(epochID, raw, softCriterion);
			} else if (plotType.equals("density") && fromTime != null
					&& toTime != null) {
				wf = new ExportService().exportSpindlesDensityToWeb(Long
						.parseLong(partID), fromTime, toTime, softCriterion);
			} else { // density
				wf = new ExportService().exportSpindlesDensityToWeb(Long
						.parseLong(partID), softCriterion);
			}

			// Set the figure scope to session
			request.getSession().setAttribute("plots.spindles." + epochID, wf);
			// Bind the figure's lifetime to session
			request.getSession().setAttribute("plots.binder.spindles." + epochID,
					new MWHttpSessionBinder(wf));	
			
			StringTemplate plot = ServletUtil.getStringTemplate("plot");
			plot.setAttribute("webFigure", ServletUtil.getWebFigureHTML(wf, "plots.spindles." + epochID));		
			
			out.println(plot.toString());			
			
		} catch (NumberFormatException e) {
			throw new ApplicationException(e);
		} catch (UserException e) {
			throw new ApplicationException(e);
		} catch (MWException e){
			  throw new ApplicationException(e);		  
		} finally {
			IOUtils.closeQuietly(out);					
		}
	}
	
	private WebFigure getEpochPlot(String txtEpochID, boolean raw,
			boolean softCriterion) throws NumberFormatException, UserException {
		DBGateway db = new DBGateway();
		DAO<Epoch> epochDAO = new DAO<Epoch>(Epoch.class, "sessionPartID");

		long epochID = Long.parseLong(txtEpochID);
		long sessionPartID = epochDAO.get(epochID).getSessionPartID();
		int samplingRate = db.getSamplingRate(sessionPartID);

		WebFigure wf = null;
		if (raw) {
			wf = ExportService.newExportServiceWithRawData().exportRawToWeb(
					epochID, softCriterion);
		} else {
			wf = ExportService.newExportServiceWithFilteredData(
					SamplingRate.toEnum(samplingRate)).exportToWeb(epochID,
					softCriterion);
		}

		return wf;
	}
	
	private void disposeWebFigure(HttpServletRequest request){
		HttpSession session = request.getSession();
		Enumeration e = session.getAttributeNames();
		while (e.hasMoreElements()) {
			String attrName = (String) e.nextElement();
			if (attrName.startsWith("plots.spindles")) {
				WebFigure previousWF = (WebFigure) session.getAttribute(attrName);
				if (previousWF != null) {
					log.info("Disposing previous WebFigure...");
					previousWF.dispose();
					previousWF = null;
					session.removeAttribute(attrName);
				}
			} else if (attrName.startsWith("plots.binder.spindles")) {
				session.removeAttribute(attrName);
			} 
		}
	}
	

}
